// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "framework.h"

#include <unordered_map>
#include "DealShm.h"

std::unordered_map<const char*, int > func_type = {
    {"MessageBoxA", 1},
    {"MessageBoxW", 2},
    {"CreateFileA", 3 },
    {"WriteFile", 4 },
    {"ReadFile", 5 },
    {"OpenFile", 6 },
    {"HeapAlloc", 7 },
    {"HeapCreate", 8 },
    {"HeapDestory", 9 },
    {"HeapFree", 10 },
    {"RegCreateKeyExA", 11 },
    {"RegSetValueExA", 12 },
    {"RegCloseKey", 13 },
    {"RegOpenKeyExA", 14 },
    {"RegDeleteValueA", 15 },
    {"WSASocketW", 16 },
    {"bind", 17 },
    {"WSASend", 18 },
    {"WSAConnect", 19 },
    {"WSARecv", 20 },
    {"closesocket", 21 },
    {"memcpy", 22 },
};

char outputStr[1000];               // 暂存调试信息
WCHAR outputWStr[1000];             // 暂存调试信息

// 共享变量使用前声明
HANDLE hSemap[2];                                           // 信号量句柄
WCHAR nameSemap[2][10] = { L"dbgSemap", L"dbgHeap" };       // 信号量名称
HANDLE hMap[2];                                             // 内存映射对象句柄
WCHAR nameShm[2][10] = { L"dbgShm", L"dgbHeap" };           // 共享内存名称
LPVOID pShm[2];                                             // 共享内存指针
func_info* shm;                                             // 函数信息结构体指针
heap_func_info* shm_heap;                                   // 堆函数信息结构体指针
std::mutex mtx[2];                                          // 互斥锁

//TODO: 定义堆释放列表结构体
typedef struct h1{
    HANDLE heap;
    int times = 0;
}heapList;
typedef struct h2{
    int num = 0;
    heapList list[100] = { 0 };
}heapListStruct;
heapListStruct heapFreeList;



// 定义和引入需要Hook的函数，和替换的函数


template<typename Tx, typename T2, typename Ty>
// 按格式写入变量dst[i]
void sprintfWithType(Tx dst, T2 i, Ty arg)
{
    if(typeid(arg)==typeid(LPCSTR)||typeid(arg)==typeid(char*))
    {
        sprintf_s(dst[i], "%s", AlterRN((LPCSTR)arg));        //AlterRN将文本中的特殊符号转换为原始字符
        //OutputDebugStringA(AlterRN((LPCSTR)arg));
    }
    else if(typeid(arg) == typeid(LPCWSTR)||typeid(arg) == typeid(WCHAR*))
    {
        sprintf_s(dst[i], "%s", AlterRN((LPCWSTR)arg));        //AlterRN将文本中的特殊符号转换为原始字符
    }
    else if (typeid(arg) == typeid(int))
    {
        sprintf_s(dst[i], "%08d", (int)arg);
    }
    else {
        sprintf_s(dst[i], "%08X", (UINT32)arg);
    }
}
// 扩展使sprintfWithType函数可接收无穷多参数， 同时，返回接收的参数个数
template <typename Args1, typename ...Args2>
int sprintfWithTypeEx(Args1 args1, Args2... args2)
{
    int i = 1;
    int arr[] = { (sprintfWithType(args1, i++, args2), 0)... };
    return i-1;
}


// 1,2 弹窗 MessageBoxA MessageBoxW
decltype(MessageBoxA)* OldMessageBoxA = MessageBoxA;
decltype(MessageBoxW)* OldMessageBoxW = MessageBoxW;

extern "C" __declspec(dllexport) int WINAPI NewMessageBoxA(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "MessageBoxA";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hWnd, lpText, lpCaption, uType);
    // 参数名
    sprintf_s(info.argName[1], "hWnd");
    sprintf_s(info.argName[2], "lpText");
    sprintf_s(info.argName[3], "lpCaption");
    sprintf_s(info.argName[4], "uType");
    // 共享内存管理
    mtx[0].lock();  
    memcpy(shm, &info, sizeof(info));
    mtx[0].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[0], 1, NULL);
    // 返回原始接口
    sprintf_s(outputStr, "new %s\nU201911729申珊靛", func_name);
    return OldMessageBoxA(NULL, outputStr, "Hooked", MB_OK);
}

extern "C" __declspec(dllexport) int WINAPI NewMessageBoxW(_In_opt_ HWND hWnd, _In_opt_ LPCWSTR lpText, _In_opt_ LPCWSTR lpCaption, _In_ UINT uType)
{    
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "MessageBoxW";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hWnd, lpText, lpCaption, uType);
    // 参数名
    sprintf_s(info.argName[1], "hWnd");
    sprintf_s(info.argName[2], "lpText");
    sprintf_s(info.argName[3], "lpCaption");
    sprintf_s(info.argName[4], "uType");
    // 共享内存管理
    mtx[0].lock();
    memcpy(shm, &info, sizeof(info));
    mtx[0].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[0], 1, NULL);
    // 返回原始接口
    return OldMessageBoxW(NULL, L"new MessageBoxW\nU201911729申珊靛", L"Hooked", MB_OK);
}


// 3,4,5,6 文件操作 CreateFileA WriteFile ReadFile OpenFile
decltype(CreateFileA)* OldCreateFileA = CreateFileA;
decltype(WriteFile)* OldWriteFile = WriteFile;
decltype(ReadFile)* OldReadFile = ReadFile;
decltype(OpenFile)* OldOpenFile = OpenFile;

extern "C" __declspec(dllexport) HANDLE WINAPI NewCreateFileA(
    LPCSTR lpFileName,
    DWORD dwDesiredAccess,
    DWORD dwShareMode,
    LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    DWORD dwCreationDisposition,
    DWORD dwFlagsAndAttributes,
    HANDLE hTemplateFile)
{
    HANDLE hFile = OldCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    if (GetFileType(hFile) == FILE_TYPE_DISK) {
        // 优先将所有的数据都存储成info，处理好，准备放入共享内存
        func_info info;                                                     // 函数信息结构体
        // 函数基础信息
        const char* func_name = "CreateFileA";                              // 函数名称
        OutputDebugStringA(func_name);
        sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
        sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
        // Hook时间戳
        GetLocalTime(&info.st);
        // ::special: FilePath
        char m[1000];
        int fileNameResult = GetFinalPathNameByHandleA(hFile, m, MAX_PATH, 0);
        doubleFan(m + 4, info.argValue[9], argValueSize);     // 让反斜杠增加一个以便json解析
        sprintf_s(info.argName[9], "FilePath");
        const char* UndefinedType = ".系统文件";
        char* lpFileType = strrchr((char*)lpFileName, '.');
        if (!lpFileType) { lpFileType = (char*)UndefinedType; };
        sprintf_s(info.argName[8], "lpFileType");
        // 参数值格式化存入，并获取参数个数
        info.argNum = 1 + sprintfWithTypeEx(info.argValue, lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile, lpFileType+1);
        // 参数名
        sprintf_s(info.argName[1], "lpFileName");
        sprintf_s(info.argName[2], "dwDesiredAccess");
        sprintf_s(info.argName[3], "dwShareMode");
        sprintf_s(info.argName[4], "lpSecurityAttributes");
        sprintf_s(info.argName[5], "dwCreationDisposition");
        sprintf_s(info.argName[6], "dwFlagsAndAttributes");
        sprintf_s(info.argName[7], "hTemplateFile");
        // 共享内存管理
        mtx[0].lock();
        memcpy(shm, &info, sizeof(info));
        mtx[0].unlock();
        // 信号量+1
        ReleaseSemaphore(hSemap[0], 1, NULL);
    }
    // 返回原始接口
    return hFile;
}

extern "C" __declspec(dllexport)BOOL WINAPI NewWriteFile(
    HANDLE       hFile,
    LPCVOID      lpBuffer,
    DWORD        nNumberOfBytesToWrite,
    LPDWORD      lpNumberOfBytesWritten,
    LPOVERLAPPED lpOverlapped
)
{
    if (GetFileType(hFile) == FILE_TYPE_DISK) {
        // 优先将所有的数据都存储成info，处理好，准备放入共享内存
        func_info info;                                                     // 函数信息结构体
        // 函数基础信息
        const char* func_name = "WriteFile";                              // 函数名称
        OutputDebugStringA(func_name);
        sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
        sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
        // Hook时间戳
        GetLocalTime(&info.st);
        // 参数值格式化存入，并获取参数个数
        // ::special: FilePath
        char m[1000];
        int fileNameResult = GetFinalPathNameByHandleA(hFile, m, MAX_PATH, 0);
        // 处理的文件的信息
        struct _stat buf;
        _stat(m + 4, &buf);
        char* lpFileName = strrchr(m, '\\');          // 查找最后一个反斜杠在哪
        const char* UndefinedType = ".系统文件";
        char* lpFileType = strrchr(lpFileName, '.');
        if (!lpFileType) { lpFileType = (char*)UndefinedType; };
        info.argNum = 1 + sprintfWithTypeEx(info.argValue, hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped,
            buf.st_size, lpFileType+1);
        sprintf_s(info.argName[6], "FileSize");
        sprintf_s(info.argName[7], "lpFileType");
        doubleFan(m + 4, info.argValue[8], argValueSize);     // 让反斜杠增加一个以便json解析，并存入参数中
        sprintf_s(info.argName[8], "FilePath");
        // 参数名
        sprintf_s(info.argName[1], "hFile");
        sprintf_s(info.argName[2], "lpBuffer");
        sprintf_s(info.argName[3], "nNumberOfBytesToWrite");
        sprintf_s(info.argName[4], "lpNumberOfBytesWritten");
        sprintf_s(info.argName[5], "lpOverlapped");
        // 共享内存管理
        mtx[0].lock();
        memcpy(shm, &info, sizeof(info));
        mtx[0].unlock();
        // 信号量+1
        ReleaseSemaphore(hSemap[0], 1, NULL);
    }
    return OldWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
}

extern "C" __declspec(dllexport) BOOL WINAPI NewReadFile(
    HANDLE hFile,
    LPVOID lpBuffer,
    DWORD nNumberOfBytesToRead,
    LPDWORD lpNumberOfBytesRead,
    LPOVERLAPPED lpOverlapped)
{
    if (GetFileType(hFile) == FILE_TYPE_DISK) {
        // 优先将所有的数据都存储成info，处理好，准备放入共享内存
        func_info info;                                                     // 函数信息结构体
        // 函数基础信息
        const char* func_name = "ReadFile";                              // 函数名称
        //OutputDebugStringA(func_name);
        sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
        sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
        // Hook时间戳
        GetLocalTime(&info.st);
        // ::special: FilePath
        char m[1000];
        int fileNameResult = GetFinalPathNameByHandleA(hFile, m, sizeof(m), 0);
        char* lpFileName = strrchr(m, '\\');          // 查找最后一个反斜杠在哪
        const char* UndefinedType = ".系统文件";
        char* lpFileType = strrchr(lpFileName, '.');
        if (!lpFileType) { lpFileType = (char*)UndefinedType; };
        // 参数值格式化存入，并获取参数个数
        info.argNum = 1 + sprintfWithTypeEx(info.argValue, hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped, lpFileType+1);
        sprintf_s(info.argName[6], "lpFileType");
        doubleFan(m + 4, info.argValue[7], argValueSize);     // 让反斜杠增加一个以便json解析
        sprintf_s(info.argName[7], "FilePath");
        // 参数名
        sprintf_s(info.argName[1], "hFile");
        sprintf_s(info.argName[2], "lpBuffer");
        sprintf_s(info.argName[3], "nNumberOfBytesToRead");
        sprintf_s(info.argName[4], "lpNumberOfBytesRead");
        sprintf_s(info.argName[5], "lpOverlapped");
        //OutputDebugStringA("test1");
        // 共享内存管理
        mtx[0].lock();
        memcpy(shm, &info, sizeof(info));
        mtx[0].unlock();
        // 信号量+1
        ReleaseSemaphore(hSemap[0], 1, NULL);
    }
    // 返回原始接口
    return OldReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
}

extern "C" __declspec(dllexport) HFILE WINAPI NewOpenFile(
    _In_    LPCSTR lpFileName,
    _Inout_ LPOFSTRUCT lpReOpenBuff,
    _In_    UINT uStyle)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "OpenFile";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    const char* UndefinedType = ".系统文件";
    char* lpFileType = strrchr((char*)lpFileName, '.');
    if (!lpFileType) { lpFileType = (char*)UndefinedType; };
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, lpFileName, lpReOpenBuff, uStyle, lpFileName, lpFileType+1);
    sprintf_s(info.argName[5], "lpFileType");      // ::special
    // 参数名
    sprintf_s(info.argName[1], "lpFileName");
    sprintf_s(info.argName[2], "lpReOpenBuff");
    sprintf_s(info.argName[3], "uStyle");
    sprintf_s(info.argName[4], "FilePath");      // ::special

    // 共享内存管理
    mtx[0].lock();
    memcpy(shm, &info, sizeof(info));
    mtx[0].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[0], 1, NULL);
    return OldOpenFile(lpFileName, lpReOpenBuff, uStyle);
}


// 7,8,9,10 堆操作 HeapAlloc HeapCreate HeapDestory HeapFree
decltype(HeapAlloc)* OldHeapAlloc = HeapAlloc;
decltype(HeapCreate)* OldHeapCreate = HeapCreate;
decltype(HeapDestroy)* OldHeapDestory = HeapDestroy;
decltype(HeapFree)* OldHeapFree = HeapFree;

extern "C" __declspec(dllexport) LPVOID WINAPI NewHeapAlloc(
    _In_ HANDLE hHeap,
    _In_ DWORD dwFlags,
    _In_ SIZE_T dwBytes)
{
    OutputDebugStringA("***********************");
    //// 优先将所有的数据都存储成info，处理好，准备放入共享内存
    //func_info info;                                                     // 函数信息结构体
    //// 函数基础信息
    //const char* func_name = "HeapAlloc";                              // 函数名称
    //OutputDebugStringA(func_name);
    //sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    //sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    //// Hook时间戳
    //GetLocalTime(&info.st);
    //// 参数值格式化存入，并获取参数个数
    //info.argNum = sprintfWithTypeEx(info.argValue, hHeap, dwFlags, dwBytes);
    //// 参数名
    //sprintf_s(info.argName[1], "hHeap");
    //sprintf_s(info.argName[2], "dwFlags");
    //sprintf_s(info.argName[3], "dwBytes");
   

    return OldHeapAlloc(hHeap, dwFlags, dwBytes);
}

extern "C" __declspec(dllexport) HANDLE WINAPI NewHeapCreate(
    DWORD fIOoptions,
    SIZE_T dwInitialSize,
    SIZE_T dwMaximumSize)
{

    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    heap_func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "HeapCreate";                               // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数     ::special
    HANDLE hHeap = OldHeapCreate(fIOoptions, dwInitialSize, dwMaximumSize);
    info.argNum = sprintfWithTypeEx(info.argValue, fIOoptions, dwInitialSize, dwMaximumSize, hHeap);
    // 参数名
    sprintf_s(info.argName[1], "hHeap");
    // 参数名
    sprintf_s(info.argName[2], "fIOoptions");
    sprintf_s(info.argName[3], "dwInitialSize");
    sprintf_s(info.argName[4], "dwMaximumSize");
    // 共享内存管理
    mtx[1].lock();
    memcpy(shm_heap, &info, sizeof(info));
    mtx[1].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[1], 1, NULL);
    // 返回原始接口
    return hHeap;
}

extern "C" __declspec(dllexport) BOOL WINAPI NewHeapDestory(
    HANDLE hHeap)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    heap_func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "HeapDestory";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hHeap);
    // 参数名
    sprintf_s(info.argName[1], "hHeap");
    // 共享内存管理
    mtx[1].lock();
    memcpy(shm_heap, &info, sizeof(info));
    mtx[1].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[1], 1, NULL);
    // 返回原始接口
    return OldHeapDestory(hHeap);
}

std::mutex mmmmmm;
extern "C" __declspec(dllexport) BOOL WINAPI NewHeapFree(
    HANDLE hHeap,
    DWORD dwFlags,
    _Frees_ptr_opt_ LPVOID lpMem)
{
    int i = 0, is_sendOut = 0;
    for (i = 0; i < heapFreeList.num; i++)
        if (hHeap == heapFreeList.list[i].heap) {
            //OutputDebugStringA("test0");
            mmmmmm.lock();
            heapFreeList.list[i].times= (heapFreeList.list[i].times+1)%51;
            if (heapFreeList.list[i].times == 50)is_sendOut = 1;
            mmmmmm.unlock();
            //OutputDebugStringA("test00");
            break;
        }
    if (i == heapFreeList.num) {            // 记录新堆
        OutputDebugStringA("test1");
        mmmmmm.lock();
        heapFreeList.list[i].heap = hHeap;
        heapFreeList.num++;
        heapFreeList.list[i].times++;
        is_sendOut = 1;
        mmmmmm.unlock();
        OutputDebugStringA("test2");
    }
    if (is_sendOut) {
        // 优先将所有的数据都存储成info，处理好，准备放入共享内存
        heap_func_info info;                                                     // 函数信息结构体
        // 函数基础信息
        const char* func_name = "HeapFree";                                 // 函数名称
        OutputDebugStringA(func_name);
        sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
        sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
        // Hook时间戳
        GetLocalTime(&info.st);
        // ::special: 增加times
        sprintf_s(info.argName[4], "times");
        sprintf_s(info.argValue[4], "%d", heapFreeList.list[i].times);
        // 参数值格式化存入，并获取参数个数
        info.argNum = 1 + sprintfWithTypeEx(info.argValue, hHeap, dwFlags, lpMem);
        // 参数名
        sprintf_s(info.argName[1], "hHeap");
        sprintf_s(info.argName[2], "dwFlags");
        sprintf_s(info.argName[3], "lpMem");
        // 共享内存管理
        mtx[1].lock();
        memcpy(shm_heap, &info, sizeof(info));
        mtx[1].unlock();
        // 信号量+1
        ReleaseSemaphore(hSemap[1], 1, NULL);
    }// 返回原始接口
    return OldHeapFree(hHeap, dwFlags, lpMem);
}


// 11,12,13,14,15 注册表操作 RegCreateKeyExA RegSetValueExA RegCloseKey RegOpenKeyExA RegDeleteValueA
decltype(RegCreateKeyExA)* OldRegCreateKeyExA = RegCreateKeyExA;
decltype(RegSetValueExA)* OldRegSetValueExA = RegSetValueExA;
decltype(RegCloseKey)* OldRegCloseKey = RegCloseKey;
decltype(RegOpenKeyExA)* OldRegOpenKeyExA = RegOpenKeyExA;
decltype(RegDeleteValueA)* OldRegDeleteValueA = RegDeleteValueA;

extern "C" __declspec(dllexport) LSTATUS WINAPI NewRegCreateKeyExA(
    HKEY hKey,
    LPCSTR lpSubKey,
    DWORD Reserved,
    LPSTR lpClass,
    DWORD dwOptions,
    REGSAM samDesired,
    const LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    PHKEY phkResult,
    LPDWORD lpdwDisposition)
{
    // ::special: hKey很可能是预定义值
    LSTATUS result = OldRegCreateKeyExA(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "RegCreateKeyExA";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition, *phkResult);
    // 参数名
    sprintf_s(info.argName[1], "hKey");
    sprintf_s(info.argName[2], "lpSubKey");
    sprintf_s(info.argName[3], "Reserved");
    sprintf_s(info.argName[4], "lpClass");
    sprintf_s(info.argName[5], "dwOptions");
    sprintf_s(info.argName[6], "samDesired");
    sprintf_s(info.argName[7], "lpSecurityAttributes");
    sprintf_s(info.argName[8], "phkResult");
    sprintf_s(info.argName[9], "lpdwDisposition");
    sprintf_s(info.argName[9], "hKey");
    // 共享内存管理
    mtx[0].lock();
    memcpy(shm, &info, sizeof(info));
    mtx[0].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[0], 1, NULL);
    // 返回原始接口
    return result;
}

extern "C" __declspec(dllexport) LSTATUS WINAPI NewRegSetValueExA(
    HKEY hKey,
    LPCSTR lpValueName,
    DWORD Reserved,
    DWORD dwType,
    const BYTE * lpData,
    DWORD cbData)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "RegSetValueExA";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hKey, lpValueName, Reserved, dwType, lpData, cbData);
    // 参数名
    sprintf_s(info.argName[1], "hKey");
    sprintf_s(info.argName[2], "lpValueName");
    sprintf_s(info.argName[3], "Reserved");
    sprintf_s(info.argName[4], "dwType");
    sprintf_s(info.argName[5], "lpData");
    sprintf_s(info.argName[6], "cbData");
    // 共享内存管理
    mtx[0].lock();
    memcpy(shm, &info, sizeof(info));
    mtx[0].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[0], 1, NULL);
    // 返回原始接口
    return OldRegSetValueExA(hKey, lpValueName, Reserved, dwType, lpData, cbData);
}

extern "C" __declspec(dllexport) LSTATUS WINAPI NewRegCloseKey(
    HKEY hKey)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "RegCloseKey";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hKey);
    // 参数名
    sprintf_s(info.argName[1], "hKey");
    // 共享内存管理
    mtx[0].lock();
    memcpy(shm, &info, sizeof(info));
    mtx[0].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[0], 1, NULL);
    // 返回原始接口
    return OldRegCloseKey(hKey);
}

extern "C" __declspec(dllexport) LSTATUS WINAPI NewRegOpenKeyExA(
    HKEY hKey,
    LPCSTR lpSubKey,
    DWORD ulOptions,
    REGSAM samDesired,
    PHKEY phkResult)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "RegOpenKeyExA";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hKey, lpSubKey, ulOptions, samDesired, phkResult);
    // 参数名
    sprintf_s(info.argName[1], "hKey");
    sprintf_s(info.argName[2], "lpSubKey");
    sprintf_s(info.argName[3], "ulOptions");
    sprintf_s(info.argName[4], "samDesired");
    sprintf_s(info.argName[5], "phkResult");
    // 共享内存管理
    mtx[0].lock();
    memcpy(shm, &info, sizeof(info));
    mtx[0].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[0], 1, NULL);
    // 返回原始接口
    return OldRegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, phkResult);
}

extern "C" __declspec(dllexport) LSTATUS WINAPI NewRegDeleteValueA(
    HKEY hKey,
    LPCSTR lpValueName)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "RegDeleteValueA";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, hKey, lpValueName);
    // 参数名
    sprintf_s(info.argName[1], "hKey");
    sprintf_s(info.argName[2], "lpValueName");
    // 共享内存管理
    mtx[0].lock();
    memcpy(shm, &info, sizeof(info));
    mtx[0].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[0], 1, NULL);
    // 返回原始接口
    return OldRegDeleteValueA(hKey, lpValueName);
}


// 16,17,18,19 socket操作 WSASocketW WSASend bind WSAConnect WSARecv closesocket
decltype(WSASocketW)* OldWSASocketW = WSASocketW;
decltype(WSASend)* OldWSASend = WSASend;
decltype(bind)* Oldbind = bind;
decltype(WSAConnect)* OldWSAConnect = WSAConnect;
decltype(WSARecv)* OldWSARecv = WSARecv;
decltype(closesocket)* Oldclosesocket = closesocket;

extern "C" __declspec(dllexport) SOCKET WSAAPI NewWSASocketW(
    int                 af,
    int                 type,
    int                 protocol,
    LPWSAPROTOCOL_INFOW lpProtocolInfo,
    GROUP               g,
    DWORD               dwFlags)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "WSASocketW";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, af, type, protocol, lpProtocolInfo, g, dwFlags);
    // 参数名
    sprintf_s(info.argName[1], "af");
    sprintf_s(info.argName[2], "type");
    sprintf_s(info.argName[3], "protocol");
    sprintf_s(info.argName[4], "lpProtocolInfo");
    sprintf_s(info.argName[5], "g");
    sprintf_s(info.argName[6], "dwFlags");
    // 共享内存管理
    mtx[0].lock();
    memcpy(shm, &info, sizeof(info));
    mtx[0].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[0], 1, NULL);
    // 返回原始接口
    return OldWSASocketW(af, type, protocol, lpProtocolInfo, g, dwFlags);
}

extern "C" __declspec(dllexport) int WSAAPI NewWSASend(
    SOCKET                             s,
    LPWSABUF                           lpBuffers,
    DWORD                              dwBufferCount,
    LPDWORD                            lpNumberOfBytesSent,
    DWORD                              dwFlags,
    LPWSAOVERLAPPED                    lpOverlapped,
    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "WSASend";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // IP port buffer     ::special
    struct sockaddr_in sa;
    int len = sizeof(sa);
    char ip[100];
    int port;
    if (!getsockname(s, (struct sockaddr*)&sa, &len))
    {
        inet_ntop(AF_INET, &sa.sin_addr, ip, sizeof(ip));
        port = ntohs(sa.sin_port);
    }
    _Field_size_bytes_(lpBuffers->len) CHAR FAR* buffers=lpBuffers->buf;
    info.argNum = sprintfWithTypeEx(info.argValue, s, buffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine, (const char*)ip, port);
    sprintf_s(info.argName[8], "IP");
    sprintf_s(info.argName[9], "port");
    // 参数名
    sprintf_s(info.argName[1], "s");
    sprintf_s(info.argName[2], "Buffers");
    sprintf_s(info.argName[3], "dwBufferCount");
    sprintf_s(info.argName[4], "lpNumberOfBytesSent");
    sprintf_s(info.argName[5], "dwFlags");
    sprintf_s(info.argName[6], "lpOverlapped");
    sprintf_s(info.argName[7], "lpCompletionRoutine");
    // 共享内存管理
    mtx[0].lock();
    memcpy(shm, &info, sizeof(info));
    mtx[0].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[0], 1, NULL);
    // 返回原始接口
    return OldWSASend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine);
}

extern "C" __declspec(dllexport) int WINAPI Newbind(
    SOCKET s,
    const sockaddr * name,
    int namelen)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "bind";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // IP port      ::special
    struct sockaddr_in* sock = (struct sockaddr_in*)name;
    int port = ntohs(sock->sin_port);
    char ip[100];
    inet_ntop(AF_INET, &sock->sin_addr, ip, sizeof(ip));
    info.argNum = sprintfWithTypeEx(info.argValue, s, name, namelen, (const char*)ip, port);
    sprintf_s(info.argName[4], "IP");
    sprintf_s(info.argName[5], "port");
    // 参数名
    sprintf_s(info.argName[1], "s");
    sprintf_s(info.argName[2], "name");
    sprintf_s(info.argName[3], "namelen");
    // 共享内存管理
    mtx[0].lock();
    memcpy(shm, &info, sizeof(info));
    mtx[0].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[0], 1, NULL);
    // 返回原始接口
    return Oldbind(s, name, namelen);
}

extern "C" __declspec(dllexport) int WSAAPI NewWSAConnect(
    SOCKET         s,
    const sockaddr*name,
    int            namelen,
    LPWSABUF       lpCallerData,
    LPWSABUF       lpCalleeData,
    LPQOS          lpSQOS,
    LPQOS          lpGQOS)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "WSAConnect";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // IP port      ::special
    struct sockaddr_in* sock = (struct sockaddr_in*)name;
    int port = ntohs(sock->sin_port);
    char ip[100];
    inet_ntop(AF_INET, &sock->sin_addr, ip, sizeof(ip));
    info.argNum = sprintfWithTypeEx(info.argValue, s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, (const char*)ip, port);
    sprintf_s(info.argName[8], "IP");
    sprintf_s(info.argName[9], "port");
    // 参数名
    sprintf_s(info.argName[1], "s");
    sprintf_s(info.argName[2], "name");
    sprintf_s(info.argName[3], "namelen");
    sprintf_s(info.argName[4], "lpCallerData");
    sprintf_s(info.argName[5], "lpCalleeData");
    sprintf_s(info.argName[6], "lpSQOS");
    sprintf_s(info.argName[7], "lpGQOS");
    // 共享内存管理
    mtx[0].lock();
    memcpy(shm, &info, sizeof(info));
    mtx[0].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[0], 1, NULL);
    // 返回原始接口
    return OldWSAConnect(s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS);
}


extern "C" __declspec(dllexport) int WSAAPI NewWSARecv(
    SOCKET                             s,
    LPWSABUF                           lpBuffers,
    DWORD                              dwBufferCount,
    LPDWORD                            lpNumberOfBytesRecvd,
    LPDWORD                            lpFlags,
    LPWSAOVERLAPPED                    lpOverlapped,
    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "WSARecv";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // IP port buffer     ::special
    struct sockaddr_in sa;
    int len = sizeof(sa);
    char ip[100];
    int port = 0;
    if (!getsockname(s, (struct sockaddr*)&sa, &len))
    {
        inet_ntop(AF_INET, &sa.sin_addr, ip, sizeof(ip));
        port = ntohs(sa.sin_port);
    }
    _Field_size_bytes_(lpBuffers->len) CHAR FAR* buffers = lpBuffers->buf;
    info.argNum = sprintfWithTypeEx(info.argValue, s, buffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine, (const char*)ip, port);
    sprintf_s(info.argName[8], "IP");
    sprintf_s(info.argName[9], "port");
    // 参数名
    sprintf_s(info.argName[1], "s");
    sprintf_s(info.argName[2], "Buffers");
    sprintf_s(info.argName[3], "dwBufferCount");
    sprintf_s(info.argName[4], "lpNumberOfBytesRecvd");
    sprintf_s(info.argName[5], "lpFlags");
    sprintf_s(info.argName[6], "lpOverlapped");
    sprintf_s(info.argName[7], "lpCompletionRoutine");
    // 共享内存管理
    mtx[0].lock();
    memcpy(shm, &info, sizeof(info));
    mtx[0].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[0], 1, NULL);
    // 返回原始接口
    return OldWSARecv(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine);
}

extern "C" __declspec(dllexport) int WSAAPI Newclosesocket(
    _In_ SOCKET s)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "closesocket";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // IP port buffer     ::special
    struct sockaddr_in sa;
    int len = sizeof(sa);
    char ip[100];
    int port;
    if (!getsockname(s, (struct sockaddr*)&sa, &len))
    {
        inet_ntop(AF_INET, &sa.sin_addr, ip, sizeof(ip));
        port = ntohs(sa.sin_port);
    }
    info.argNum = sprintfWithTypeEx(info.argValue, s, (const char*)ip, port);
    sprintf_s(info.argName[2], "IP");
    sprintf_s(info.argName[3], "port");
    // 参数名
    sprintf_s(info.argName[1], "s");
    // 共享内存管理
    mtx[0].lock();
    memcpy(shm, &info, sizeof(info));
    mtx[0].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[0], 1, NULL);
    // 返回原始接口
    return Oldclosesocket(s);
}


// 20 内存拷贝 memcpy
decltype(memcpy)* Oldmemcpy = memcpy;

extern "C" __declspec(dllexport) void* __cdecl Newmemcpy(
    void* _Dst,
    const void* _Src,
    size_t _Size)
{
    // 优先将所有的数据都存储成info，处理好，准备放入共享内存
    func_info info;                                                     // 函数信息结构体
    // 函数基础信息
    const char* func_name = "memcpy";                              // 函数名称
    OutputDebugStringA(func_name);
    sprintf_s(info.argName[0], "%d", func_type[func_name]);             // 编号
    sprintf_s(info.argValue[0], "%s", func_name);                       // 函数名称
    // Hook时间戳
    GetLocalTime(&info.st);
    // 参数值格式化存入，并获取参数个数
    info.argNum = sprintfWithTypeEx(info.argValue, _Dst, _Src, _Size);
    // 参数名
    sprintf_s(info.argName[1], "_Dst");
    sprintf_s(info.argName[2], "_Src");
    sprintf_s(info.argName[3], "_Size");
    // 共享内存管理
    mtx[0].lock();
    memcpy(shm, &info, sizeof(info));
    mtx[0].unlock();
    // 信号量+1
    ReleaseSemaphore(hSemap[0], 1, NULL);
    // 返回原始接口
    return Oldmemcpy(_Dst, _Src, _Size);
}


// Question: 究竟用WINAPI还是APIENTRY？？？(都一样，都是指示编译器按照API的参数入栈方式编译。看引用模式，它被define成WINAPI)
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH://加载进程时调用的代码
    {   
        /*char m[100000];
        GetModuleFileNameA(NULL, m, MAX_PATH);
        if (!strcmp(m, "E:\\资料\\计算机\\软件安全\\课设\\TestInitialNullForStudent\\InjectDll\\Release\\TestConsole.exe"))break;*/
        //GetModuleFileNameA(0, outputStr, 256);
        //OutputDebugStringA(outputStr);
        //初始化共享内存的全局参数
        shm = (func_info*)InitShm(hSemap[0], hMap[0], pShm[0], nameSemap[0], nameShm[0]);
        shm_heap = (heap_func_info*)InitShm(hSemap[1], hMap[1], pShm[1], nameSemap[1], nameShm[1]);
        
        
        DetourRestoreAfterWith();       // Question: 这个用来干什么的？
        DisableThreadLibraryCalls(hModule);
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());

        DetourAttach(&(PVOID&)OldMessageBoxA, NewMessageBoxA);
        
        DetourAttach(&(PVOID&)OldMessageBoxW, NewMessageBoxW);
        DetourAttach(&(PVOID&)OldCreateFileA, NewCreateFileA);
        DetourAttach(&(PVOID&)OldWriteFile, NewWriteFile);
        DetourAttach(&(PVOID&)OldReadFile, NewReadFile);
        DetourAttach(&(PVOID&)OldOpenFile, NewOpenFile);
        //DetourAttach(&(PVOID&)OldHeapAlloc, NewHeapAlloc);
        DetourAttach(&(PVOID&)OldHeapCreate, NewHeapCreate);
        DetourAttach(&(PVOID&)OldHeapDestory, NewHeapDestory);
        DetourAttach(&(PVOID&)OldHeapFree, NewHeapFree);
        //DetourAttach(&(PVOID&)OldRegCreateKeyExA, NewRegCreateKeyExA);
        DetourAttach(&(PVOID&)OldRegSetValueExA, NewRegSetValueExA);
        DetourAttach(&(PVOID&)OldRegCloseKey, NewRegCloseKey);
        DetourAttach(&(PVOID&)OldRegOpenKeyExA, NewRegOpenKeyExA);
        DetourAttach(&(PVOID&)OldRegDeleteValueA, NewRegDeleteValueA);
        DetourAttach(&(PVOID&)OldWSASocketW, NewWSASocketW);
        DetourAttach(&(PVOID&)OldWSASend, NewWSASend);
        DetourAttach(&(PVOID&)Oldbind, Newbind);
        DetourAttach(&(PVOID&)OldWSAConnect, NewWSAConnect);
        DetourAttach(&(PVOID&)OldWSARecv, NewWSARecv);
        DetourAttach(&(PVOID&)Oldmemcpy, Newmemcpy);
        

        DetourTransactionCommit();
        break;
    }
    case DLL_THREAD_ATTACH://加载线程时
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
    {
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());

       DetourDetach(&(PVOID&)OldMessageBoxA, NewMessageBoxA);
        DetourDetach(&(PVOID&)OldMessageBoxW, NewMessageBoxW);
        DetourDetach(&(PVOID&)OldCreateFileA, NewCreateFileA);
        DetourDetach(&(PVOID&)OldWriteFile, NewWriteFile);
        DetourDetach(&(PVOID&)OldReadFile, NewReadFile);
        DetourDetach(&(PVOID&)OldOpenFile, NewOpenFile);
        //DetourDetach(&(PVOID&)OldHeapAlloc, NewHeapAlloc);
        DetourDetach(&(PVOID&)OldHeapCreate, NewHeapCreate);
        DetourDetach(&(PVOID&)OldHeapDestory, NewHeapDestory);
        DetourDetach(&(PVOID&)OldHeapFree, NewHeapFree);
        DetourDetach(&(PVOID&)OldRegCreateKeyExA, NewRegCreateKeyExA);
        DetourDetach(&(PVOID&)OldRegSetValueExA, NewRegSetValueExA);
        DetourDetach(&(PVOID&)OldRegCloseKey, NewRegCloseKey);
        DetourDetach(&(PVOID&)OldRegOpenKeyExA, NewRegOpenKeyExA);
        DetourDetach(&(PVOID&)OldRegDeleteValueA, NewRegDeleteValueA);
        DetourDetach(&(PVOID&)OldWSASocketW, NewWSASocketW);
        DetourDetach(&(PVOID&)OldWSASend, NewWSASend);
        DetourDetach(&(PVOID&)Oldbind, Newbind);
        DetourDetach(&(PVOID&)OldWSAConnect, NewWSAConnect);
        DetourDetach(&(PVOID&)OldWSARecv, NewWSARecv);
        DetourDetach(&(PVOID&)Oldmemcpy, Newmemcpy);

        DetourTransactionCommit();

        DestoryShm(hMap[0], pShm[0]);
        DestoryShm(hMap[1], pShm[1]);
        break;
    }
    }
    return TRUE;
 }

